import { Component, OnInit, LOCALE_ID } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { Router } from '@angular/router';
import {
  FormBuilder,
  FormGroup,
  Validators
} from '@angular/forms';
import { NzMessageService } from 'ng-zorro-antd';
import { NzNotificationService } from 'ng-zorro-antd';
import * as Cookies from 'js-cookie';
import { Subject } from 'rxjs';
import { debounceTime, distinctUntilChanged } from 'rxjs/operators';

import { Constant } from '@core/constant';
import { environment } from '@env/environment';

import { StartupService } from '@core/startup/startup.service';
import { I18NService } from '@core/i18n/i18n.service';
import { SettingsService } from '@core/settings/settings.service';
import { SystemUserService } from '@core/system/system-user.service';
import { TokenService } from '@core/auth/token/token.service';
import { PassportService } from '../services/passport.service';
import { check } from '@core/auth/token/utils';
import { AES, SHA, MD5 } from '@shared/utils/security.utils';
import {Debugger} from "inspector";

@Component({
  selector: 'app-login',
  templateUrl: './login.html'
})

export class LoginComponent implements OnInit {

  constructor(
    private sanitizer: DomSanitizer,
    private fb: FormBuilder,
    private router: Router,
    private message: NzMessageService,
    private notification: NzNotificationService,
    private i18nService: I18NService,
    private startupService: StartupService,
    public settings: SettingsService,
    private tokenService: TokenService,
    private systemUserService: SystemUserService,
    private passportService: PassportService
  ) {
    this.validateForm = this.fb.group({
      account: [null, [Validators.required]],
      password: [null, [Validators.required]],
      verify: [null, [Validators.required]],
      remember: [false]
    });
    this.getVerify();
  }

  validateForm: FormGroup;

  verify: any;

  private verifyToken: string;

  isCheck = true;

  loadingVerify = false;

  private accountText: Subject<any> = new Subject<any>();

  get langs() {
    return this.i18nService.getLangs();
  }

  get i18n() {
    return environment.i18n;
  }

  initLoginInfo(): void {
    this.accountText.pipe(
       // 请求防抖
       debounceTime(300),
       distinctUntilChanged()
    ).subscribe(res => {
      this.getRemember(res);
    });
  }

  accountChange(e): void {
    if (!this.validateForm.value.account) {
      this.validateForm.patchValue({
        password: null
      });
    }
    this.accountText.next(this.validateForm.value.account);
  }

  ngOnInit(): void {
    if (check(this.tokenService.get())) {
      this.router.navigate(['/main']);
    } else {
      this.systemUserService.clearLoginMsg();
      this.getRemember();
      this.initLoginInfo();
    }
  }

  getFormControl(name) {
    return this.validateForm.controls[name];
  }

  submitForm(): void {
    this.login(this.validateForm.value.account, this.validateForm.value.password, this.validateForm.value.verify);
  }

  login(account: string, password: string, verify: string): void {
    if (this.isCheck) {
      this.isCheck = false;
      this.passportService.login(account, password, verify, this.verifyToken).subscribe(res => {
        if (res) {
          this.message.success(this.i18nService.translate('login.return.login_success'));
          this.remember(account, password);
          const t = this;
          this.startupService.load();
          setTimeout(() => {
            t.router.navigate([this.passportService.redirectUrl ? this.passportService.redirectUrl : '/' + Constant.MAIN_PATH]);
          }, 300);
        } else {
          this.message.error(this.i18nService.translate('login.return.login_failure'));
          this.refreshVerify();
        }
        this.isCheck = true;
      }, err => {
        this.isCheck = true;
        this.refreshVerify();
      });
    }
  }

  getVerify(): void {
    this.loadingVerify = true;
    this.passportService.verify().subscribe(res => {
      this.verify = this.sanitizer.bypassSecurityTrustResourceUrl('data:image/png;base64,' + res.base64);
      this.verifyToken = res.vToken;
      this.loadingVerify = false;
    }, err => {
      this.verify = null;
      this.loadingVerify = false;
    });
  }

  refreshVerify(): void {
    if (this.loadingVerify) {
      return;
    }
    this.getVerify();
  }

  forgotPassword(): void {
    this.notification.info(this.i18nService.translate('login.text.forget'), this.i18nService.translate('login.return.forget'));
  }

  switchLanguage(lang): void {
    this.i18nService.use(lang);
    this.settings.setLayout('lang', lang);
  }

  remember(account: string, password: string): void {
    if (!this.validateForm.value.remember) {
      Cookies.remove(Constant.REMEMBERKEY);
      return;
    }
    const key = SHA.sha1(account).substring(0, 8);
    const s = SHA.sha1(password).substring(0, 8);
    const passwordEncrypt = AES.encrypt(password, key + s);
    const data = {
      a: account,
      p: passwordEncrypt,
      s: s
    };
    const encryptStr = AES.encrypt(JSON.stringify(data), MD5(Constant.AESLOGINKEY).substring(0, 16));
    if (Cookies.get(Constant.REMEMBERKEY) !== encryptStr) {
      Cookies.set(Constant.REMEMBERKEY, encryptStr, {
        expires: 30,
        domain: environment.cookie.doMain,
        path: environment.cookie.path
      });
    }
  }

  getRemember(account?: string): void {
    const encryptStr = Cookies.get(Constant.REMEMBERKEY);
    if (encryptStr != null) {
      const decryptStr = AES.decrypt(encryptStr, MD5(Constant.AESLOGINKEY).substring(0, 16));
      const data = JSON.parse(decryptStr);
      const password = AES.decrypt(data.p, SHA.sha1(data.a).substring(0, 8) + data.s);
      if (account !== undefined && account !== data.a) {
        this.validateForm.patchValue({
          password: null
        });
        return;
      }
      const loginInfo = {
        account: data.a,
        password: password,
        remember: true
      };
      this.validateForm.patchValue(loginInfo);
    }
  }
}
